/*
 * Copyright (c) 2010-2013 Ruben Chakhmakhchyan. All rights reserved.
 * 
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Eclipse Public License
 * Version 1.0 (the 'License'). You may not use this file except in
 * compliance with the License. Please obtain a copy of the License at
 * http://opensource.org/licenses/EPL-1.0 and read it before using this file.
 */

#pragma once


#include "commontypes.h"
#include "async_invoke.h"
#include "message_listener.h"
#include "image_acquisition_model.h"
#include "list.h"
#include "event_handlers.h"

#ifdef _WINDOWS

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <windows.h>
#endif


enum class TransferMode
{
    Default = -1,
    Native = 0,
    File = 1,
    Memory = 2
};

enum class DocumentFormat
{
    Default,	// image/jpeg
    Bmp,		// image/bmp
    Jpeg,		// image/jpeg
    Gif,		// image/gif
    Tiff,		// image/tiff
    Png,		// image/png 
    Pdf,		// image/pdf

};

enum class ImageFormat
{
    Default,	// image/jpeg
    Bmp,		// image/bmp
    Jpeg,		// image/jpeg
    Gif,		// image/gif
    Tiff,		// image/tiff
    Png,		// image/png 
    Dib

};

enum class ImageFilter : int
{
    None = 0,
    //ASCIIHexDecode,		// AHx
    //ASCII85Decode,		// A85
    //LZWDecode,			// LZW
    Flate = 1,				// FlateDecode - (PDF 1.2) Fl (uppercase F, lowercase L)
    //RunLengthDecode,		// RL
    CCITT = 2,				// CCITTFaxDecode - CCF
    DCT = 3,				// DCTDecode - DCT
};

typedef struct ImageProps
{
    uint_t width;			// width in pixels
    uint_t height;			// height in pixels
    uint_t resolution;		// resolution in dpi
    byte_t bitCount;		// bits per pixel
    byte_t bitsPerChannel;	// bits per channel
    PixelType pixelType;	// pixe type
    bool paletteInverted;	// palette inverted (for monochrome images)
    bool isBlank;			// indicates whether the image is blank
} ImageProps;

enum class InteractiveTool
{
    None,
    Zoom,
    Pan,
    Crop
};

// Plugin Model operations
enum class ModelFeature
{
    Scan,
#ifndef _ADDON
    Upload
#endif
};

// Operation states
enum class ModelActionState
{
    Idle,
    Active
};

// Compression format for stored images
enum class StoreFormat
{
    None = 0,
    Zlib = 1,
    Jpeg = 2
};


__interface Plugin;


__interface PluginImage
{
public:

    //virtual ~PluginImage() { }

    virtual long getWidth() const = 0;
    virtual long getHeight() const = 0;
    virtual PixelType getPixelType() const = 0;
    virtual long getResolution() const = 0;
    virtual void* getTag() const = 0;
    virtual void setTag( void* value ) = 0;
    virtual void setEventHandler( DisposeEventHandler* value ) = 0;
    virtual bool getImageData( List<byte_t>& list, int x, int y, int width, int height ) = 0;
    virtual const char* getThumbnailUrl() = 0;
    virtual int getIndex() const = 0;
    virtual uint32_t getPixel( int x, int y ) = 0;
    virtual void setPixel( int x, int y, uint32_t value ) = 0;
};


__interface PluginModel
{
public:

    //virtual ~PluginModel() { }

    virtual bool getPlatformSupported() = 0;
    virtual Plugin* getPlugin() = 0;
    virtual ImageAcquisitionModel* getIaModel() = 0;

    // Performs the scanning.
    //	add:	If true - the new scan is added to the existing list, if false - the current image is overridden.
    //  Returns the number of pages acquired in this session.
    virtual ResultCode scan( bool add, int& numberOfImages ) = 0;

    // Begins the asynchronous scan.
    virtual bool beginScan( bool add, AsyncCallback pAsyncCallback ) = 0;
#ifndef _ADDON
    virtual void upload() = 0;

    // Begins the asynchronous upload.
    virtual bool beginUpload( DocumentFormat format, char* url, List<char*>* filenames, int indices[], int count, AsyncCallback pAsyncCallback, int id ) = 0;
#endif
    virtual bool beginSave( DocumentFormat format, bool multipage, wchar_t* path, List<wchar_t*>* filenames, int indices[], int indexCount, AsyncCallback pAsyncCallback, int id ) = 0;

    virtual bool hasImage() = 0;

#ifdef _WINDOWS
    virtual void render( HDC hdc ) = 0;
#endif

    virtual void requestUpdateView() = 0;
    virtual void resize( size_t width, size_t height ) = 0;
    virtual bool saveToFile( wchar_t* path, DocumentFormat format, int indices[], int count ) = 0;

    virtual void setImage( Pixels& image, bool add = true ) = 0;

    virtual bool stringToDocumentFormat( const wchar_t* string, DocumentFormat& format ) = 0;
    virtual bool stringToDocumentFormat( const char* string, DocumentFormat& format ) = 0;

    virtual int getSelectedImageIndex() = 0;
    virtual void selectImage( int index, bool refreshIfActive = false ) = 0;
    virtual void selectNextImage() = 0;
    virtual void selectPreviousImage() = 0;
    virtual int getImageCount() = 0;

    virtual uint_t getImageQuality() = 0;
    virtual void setImageQuality( uint_t value ) = 0;

    // tools

    // zoom
    virtual bool getZoomState() = 0;
    virtual void setZoomState( bool value, bool isInternal = false ) = 0;
    virtual double getZoom() = 0;
    virtual void setZoom( double factor ) = 0;
    virtual double getZoomStep() = 0;
    virtual void setZoomStep( double step ) = 0;
    virtual double getZoomFit() = 0;
    virtual void resetZoom() = 0;

    // pan
    virtual bool getPanState() = 0;
    virtual void setPanState( bool value, bool isInternal = false ) = 0;
    virtual bool panX( int delta, bool updateView = true ) = 0;
    virtual bool panY( int delta, bool updateView = true ) = 0;
    virtual bool pan( int dx, int dy ) = 0;

    virtual void mouseLeftDown( short xpos, short ypos ) = 0;
    virtual void mouseLeftUp( short xpos, short ypos ) = 0;
    virtual void mouseMove( short xpos, short ypos ) = 0;
    virtual bool keyDown( uint_t key ) = 0;
    virtual bool keyUp( uint_t key ) = 0;

    // rotate
    virtual bool rotate( int degrees ) = 0;

    // crop
    virtual bool getCropState() = 0;
    virtual void setCropState( bool value, bool isInternal = false ) = 0;
    virtual bool crop() = 0;
    virtual bool crop( int left, int top, int width, int height ) = 0;

    virtual InteractiveTool getCurrentTool() = 0;

    // image capabilities
    virtual PixelType getPixelType() const = 0;
    virtual void setPixelType( const PixelType value ) = 0;
    virtual int getResolution() const = 0;
    virtual void setResolution( const int value ) = 0;
    virtual int getContrast() const = 0;
    virtual void setContrast( const int value ) = 0;

    // device capabilities
    virtual TransferMode getTransferMode() const = 0;
    virtual void setTransferMode( TransferMode value ) = 0;
    virtual PaperSource getPaperSource() = 0;
    virtual void setPaperSource( PaperSource value ) = 0;
    virtual bool getDuplex() = 0;
    virtual void setDuplex( bool value ) = 0;

    virtual int getDriverModel() const = 0;
    virtual bool setDriverModel( int value ) = 0;
    virtual bool getDevices() = 0;
    virtual ImagingDevice* getDevice( int id ) = 0;
    virtual int getDeviceCount() = 0;
    virtual bool getDevicesRefreshed() = 0;
    virtual void setDevicesRefreshed( bool value ) = 0;
    virtual bool getShowDeviceUI() = 0;
    virtual void setShowDeviceUI( bool value ) = 0;
    virtual int getDeviceIndex() = 0;
    virtual void setDeviceIndex( int index ) = 0;

    virtual void getViewSize( int& width, int& height ) = 0;
    virtual void setViewSize( const int width, const int height ) = 0;

    virtual bool connect() = 0;
    virtual void disconnect() = 0;
    virtual bool getIsConnected() = 0;

    virtual void clearImages() = 0;

    virtual uint_t getImageThumbnailSize() const = 0;
    virtual void setImageThumbnailSize( uint_t value ) = 0;

    virtual const char* getImageThumbnailUrl( int index ) const = 0;

    virtual const char* getVersion() const = 0;

    virtual ImageFilter getFilter( DocumentFormat format, PixelType pixelType ) const = 0;
    virtual void setFilter( DocumentFormat format, PixelType pixelType, ImageFilter filter ) = 0;

    virtual bool getAutoPosition() = 0;
    virtual void setAutoPosition( bool value ) = 0;

    virtual bool getAutoCompress() = 0;
    virtual void setAutoCompress( bool value ) = 0;

    virtual int getAutoCompressionLevel() = 0;
    virtual void setAutoCompressionLevel( int value ) = 0;

    virtual bool getAutoPause() = 0;
    virtual void setAutoPause( bool value ) = 0;

    virtual bool parseIndices( const char* rangeString, int*& indices, int& count ) = 0;

    virtual bool getAutoCompressInBackground() = 0;
    virtual void setAutoCompressInBackground( bool value ) = 0;

    virtual StoreFormat getStoreFormat() = 0;
    virtual void setStoreFormat( StoreFormat value ) = 0;

    virtual void initializeDevice() = 0;

    virtual double getPageWidth() const = 0;
    virtual void setPageWidth( double value ) = 0;

    virtual double getPageHeight() const = 0;
    virtual void setPageHeight( double value ) = 0;

    virtual void resumeScan( bool proceed ) = 0;

    virtual void pauseScan() = 0;
    virtual void stopScan() = 0;

    virtual bool deleteImage( int index ) = 0;
    virtual bool shiftImage( int direction ) = 0;
    virtual bool moveImage( int index ) = 0;

    virtual const PluginImage* getImage( int index ) = 0;

    //virtual ModelProcessState getOperationState( ModelState
};

PluginModel* CreatePluginModel( Plugin* pPlugin, MessageListener* messageListener );
